package com.zillow.channelwriter2;

import com.zillow.channelwriter2.cache.LruCache1;
import com.zillow.channelwriter2.walle.PackageUtil;
import com.zillow.channelwriter2.walle.reader.SignatureNotFoundException;
import com.zillow.channelwriter2.walle.writer.ChannelWriter;
import org.apache.catalina.connector.RequestFacade;
import org.apache.catalina.connector.ResponseFacade;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

@SpringBootApplication
@RestController
public class ChannelWriter2Application {

    @Value("${file.upload.root.dir}")
    String fileUploadRootDir;


    private String checkUpdateApi = "http://xq.ji7.com/download/app_android_version";

    private String apkUrl = "";

    private long version = 0;

    /**
     * key : id
     * value: apk filename
     */
    LruCache1<String, String> apkCache = new LruCache1<String, String>(500) {

        @Override
        protected void onItemEvicted(String key, String item) {

            File file = new File(fileUploadRootDir, item);
            if (file.exists()) {
                boolean r = file.delete();
            }
        }
    };


    /**
     * 下载安装包
     *
     * @param httpRequest ..
     * @param response    ..
     * @return
     */
    @GetMapping("api/download/{id}")
    public void download(RequestFacade httpRequest, ResponseFacade response) {

        //确保是最新的包，没有则下载
//        ensureLatest();

        ensureBaseApk();
        String reqUri = httpRequest.getRequestURI();

        FileInputStream fis = null;
        int beginIndex = reqUri.lastIndexOf("/");
        if (beginIndex > 0) {
            String id = reqUri.substring(beginIndex + 1);

            try {
                File channelFile = createChannelFile(id);
                apkCache.put(id, channelFile.getName());
                response.setContentType("application/force-download");// 设置强制下载不打开
                response.setContentLength((int) channelFile.length());
                response.addHeader("Content-Disposition", "attachment;fileName=" + channelFile.getName());// 设置文件名
                fis = new FileInputStream(channelFile);
                IOUtils.copyLarge(
                        new BufferedInputStream(fis),
                        response.getOutputStream());

            } catch (IOException e) {


                e.printStackTrace();
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }


    synchronized void ensureLatest() {
        try {
            boolean hasUpdate;
            HttpURLConnection urlConnection = (HttpURLConnection) new URL(checkUpdateApi).openConnection();
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            InputStream stream = urlConnection.getInputStream();
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = stream.read(buffer)) != -1)
                bos.write(buffer, 0, len);

            stream.close();
            JSONObject json = new JSONObject(new String(bos.toByteArray()));
            JSONObject dataObj = json.getJSONObject("data");
            long apkVersion = dataObj.getLong("apk_version");
            hasUpdate = apkVersion > versionNow();
            apkUrl = dataObj.getString("apk_path");

            if (hasUpdate) {
                downLoadLatestApk(apkUrl);
            }
            bos.close();
            stream.close();

        } catch (IOException | JSONException e) {
            e.printStackTrace();
        }
    }

    private void downLoadLatestApk(String apkUrl) {
        try {
            HttpURLConnection urlConnection = (HttpURLConnection) new URL(apkUrl).openConnection();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            BufferedInputStream bis = new BufferedInputStream(urlConnection.getInputStream());
            int len;
            byte[] buf = new byte[2048];
            while ((len = bis.read(buf)) != -1)
                baos.write(buf, 0, len);
            baos.flush();
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(fileUploadRootDir, "app.apk")));
            bos.write(baos.toByteArray());
            bos.flush();


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private long versionNow() {
        if (version <= 0) {
            return (version = readLocalVersion());
        } else return version;
    }


    private long readLocalVersion() {

        File file = new File(fileUploadRootDir, "app.apk");
        if (!file.exists())
            return 0L;
        return PackageUtil.readApkVersion(file);
    }

    private File createChannelFile(String id) {

        try {
            File pathRoot = new File(fileUploadRootDir);
            makeAppFolderIfNotExists();
            File file = new File(pathRoot.getAbsolutePath(), "app.apk");

            File newFile = new File(pathRoot.getAbsolutePath(), getApkFileName(id));

            File channelFile = copyNewFileIfNotExists(file, newFile);

            //打入 id 信息
            ChannelWriter.put(channelFile, id, false);

            return channelFile;

        } catch (IOException e) {
            System.out.println("拷贝文件错误");
        } catch (SignatureNotFoundException e) {
            System.out.println("渠道打包签名错误");
        }


        throw new IllegalStateException("复制文件错误系统错误");
    }

    private static String getApkFileName(String id) {

        return "apk_inviter_" +
                id +
                ".apk";

    }

    private void ensureBaseApk() {

        File baseApk = new File(fileUploadRootDir, "app.apk");

        if (!baseApk.exists()) {

            try {

                ClassPathResource resourceApk = new ClassPathResource("static/app.apk");
                FileUtils.copyInputStreamToFile(resourceApk.getInputStream(), baseApk);

            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    private void makeAppFolderIfNotExists() {
        File file = new File(fileUploadRootDir);
        if (!file.exists() && file.isDirectory())
            file.mkdirs();

    }


    @PostMapping("/error")
    @GetMapping("/error")
    public static String error() {

        return "系统错误";
    }

    private static File copyNewFileIfNotExists(File srcFile, File newFile) {

        try {

            if (!newFile.exists() || newFile.length() <= srcFile.length())
                FileUtils.copyFile(srcFile, newFile);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return newFile;
    }


    public static void main(String[] args) {
        SpringApplication.run(ChannelWriter2Application.class, args);
    }

}
